home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
076-100
/
087
/
warptext
/
warptext.asm
< prev
next >
Wrap
Assembly Source File
|
1995-03-13
|
18KB
|
427 lines
* --------------------------------------------------------------------------
* WarpText.asm -- (PRE-RELEASE!) an ultra-fast, Bill Kelly
* super_spiffy text-emitting routine. :-) 06/04/87
*
* Copyright 1987 by Bill W. Kelly.
*
* THANKS:
*
* Many thanks to Hayes C. Haugen for giving me the idea to write
* these routines-- I took one look at Blitz and thought:
* "I've *gotta* DO that!" Well, thanks, Hayes -- I've done it.
* Now, if I could *only* make a file requestor as nice as yours!!! :-)
*
* Thanks also to the people who gave me suggestions about ways to improve
* the WarpText routines I had originally written! These are much nicer...
*
* COPYRIGHT NOTICE:
*
* This code, and the name "WarpText," is Copyright 1987 by Bill W. Kelly.
*
* DISTRIBUTION INFORMATION:
*
* You may distribute this code in any way you want to. I would prefer
* that you charge less than $10 for distribution, however, and please
* leave this whole notice intact. Please also distribute the file
* "WarpText.i" together with "WarpText.asm" (this file). Thanks!
*
* NOTE: IF YOU ARE GOING TO MODIFY THE CODE, please make a little note
* containing the date, what the original code was, and anything
* else you deem necessary...
*
* USING WARPTEXT IN A PROGRAM:
*
* That's what it's here for!
*
* If you are going to distribute the source code with your program
* please follow the restrictions under "DISTRIBUTION INFORMATION."
*
* It would be neat, especially if you aren't distributing the source
* with your program, if you could find a place somewhere in your program
* (the "ABOUT" menu, for instance) to say something like,
* "Using Bill Kelly's WarpText routines for speed!," however if you
* don't seem to be able to do this... don't worry about it. I would
* really appreciate it, though! Thanks!
*
* PLEASE CONTACT ME BEFORE USING THIS CODE IN A COMMERCIAL PROGRAM!
*
* MY ADDRESS:
*
* NAME: Bill W. Kelly
* UUCP: {akgua, hplabs!hp-sdd, sdcsvax}!crash!pnet01!billk
* ARPA: crash!pnet01!billk@nosc
* INET: billk@pnet01.CTS.COM | For UUCP, don't do just pnet01!billk;
* USPS: 2507 Caminito La Paz | please include the crash!pnet01!billk.
* La Jolla, CA 92037 | Thanks!
* FONE: (619) 454-1307
*
* PRE-RELEASE:
*
* This is a pre-release version of WarpText. In about half a month or
* a month I plan to release a version of WarpText that comes with
* an example program and has any reported bugs fixed. I will also
* be adding a real clearscreen (clear 'window') on a formfeed and some
* other features. If any of the code looks strange, or you notice
* that I'm doing something like "moveq #0,dn" where I don't need to...
* Well, you might mention it to save me time, although I will be going
* back over the code to look for little things like this...
* I took as much time as my schedule would permit to write this and get
* it debugged and out. There are probably a few strange or unneeded
* things I've done -- I haven't *really* LOOKED at the code yet,
* though I have tested it... Ah well...
*
* GEE, THAT'S ALL VERY NICE, BUT HOW DO I CALL THESE ROUTINES???
*
* Well, I have given you yet another structure to deal with...
* Let me introduce you to WarpInfo...
*
* STRUCTURE WarpInfo,0 ; ...the <I> denotes internal use.
* APTR wi_TextFont ; Pointer to a TextFont structure.
* APTR wi_BitMap ; Pointer to a BitMap structure.
* WORD wi_WhichPlane ; Which bitplane to render into.
* WORD wi_Left ; Left edge of 'window' in char loc's.
* WORD wi_Top ; Top edge of 'window' in char loc's.
* WORD wi_Width ; Width of 'window' in char loc's.
* WORD wi_Height ; Height of 'window' in char loc's.
* APTR wi_WindowTop ; <I> Address of top of 'window.'
* APTR wi_CurLine ; <I> Address of start of current line.
* APTR wi_LastLine ; <I> Address of start of last line.
* WORD wi_CurX ; <I> Current X position.
* WORD wi_LastX ; <I> Maximum X position on a line.
* WORD wi_BPMod ; <I> # total possible chars on a line in bp
* WORD wi_Modulo ; <I> Add this to get to next line.
* LABEL wi_SIZE
*
* When you assemble WarpText.asm, it will expect to find this structure
* in graphics directory of your include files. It will do:
* INCLUDE "graphics/warptext.i" I have already created a file called
* "WarpText.i" which should be distributed along with this file.
*
* Now about the routines: there are only four routines that make up
* WarpText. You must call the InitWarpInfo routine before calling any
* of the other three routines.
*
* Please see each routine for information about how to call them.
*
* OH YEAH, BUG REPORTS:
*
* What, bugs in *my* code??? (Shut up, Bill...!)
*
* I would really appreciate hearing about the problems you find in
* my code! I welcome your input. 'Ya know, suggestions, questions,
* comments, flames?, etc...
*
* Remember, this is a pre-release version of WarpText. I plan to release
* a version that *actually* has an EXAMPLE program with it. (Gee...)
* In this version I will fix all the reported bugs and may make some
* changes if anyone comes up with any interesting suggestions.
*
* Anyway,
*
* HAVE FUN! Bill
* --------------------------------------------------------------------------
XDEF InitWarpInfo
XDEF GotoXY
XDEF GetXY
XDEF WarpText
NOLIST ; I don't want to see all of this junque...
INCLUDE "graphics/text.i"
INCLUDE "graphics/gfx.i"
INCLUDE "graphics/warptext.i"
LIST ; Turn listing back on...
* -----------------------------------------
* Seems like a good place to put some code:
* -----------------------------------------
CODE ; Ready...FIRE! ...Aim?
* --------------------------------------------------------------------------
* INITWARPINFO NEEDS:
*
* a0 - Pointer to an instance of the WarpInfo structure, with the following
* fields initialized:
*
* wi_TextFont: Pointer to an open font. (I.e. what OpenFont() returns
* to you, other than NULL.)
* wi_BitMap: Pointer to an initialized, 'working' BitMap structure.
* (E.g. Open a window. Get the pointer to the screen
* out of wd_WScreen. From there the BitMap structure is
* at sc_BitMap, which is an offset, not a pointer, into
* the Screen structure.)
* wi_WhichPlane: Which bitplane you want the routine to draw into.
* Numbering begins at zero. On the Workbench screen
* (or any two-bitplane screen) the possible numbers for
* wi_WhichPlane are 0 and 1.
* wi_Left: Left edge of the 'window' (in character locations)
* you want the routine to write into.
* wi_Top: Top edge of the 'window' in character locations.
* wi_Width: Width of 'window' (also on character locations).
* wi_Height: Height of 'window' -- guess what? Character locations.
*
* REGISTER USAGE FOR INITWARPINFO:
*
* d0 - Left, Top, Width, Height, etc.
* d1 - wi_Modulo
* d2 - Scratch
* d3 - Y size of font
* d4 - Scratch
*
* a0 - Pointer to WarpInfo structure with above fields initialized.
* a1 - Addr of top of bitplane, wi_WindowTop, etc.
* a2 - Scratch
* --------------------------------------------------------------------------
InitWarpInfo: movem.l d0-d4/a1-a2,-(sp)
moveq #0,d4 ; Clear scratch.
move.w d4,wi_CurX(a0) ; Store it in WarpInfo.
move.w wi_Width(a0),wi_LastX(a0) ; Max X position.
move.l wi_BitMap(a0),a1 ; Get some stuff from bmap.
moveq #0,d2
move.w bm_BytesPerRow(a1),d2 ; #bytes per row in d2
move.w d2,wi_BPMod(a0) ; #bytes per row->wi_BPMod
move.w wi_WhichPlane(a0),d4 ; Get bitplane#.
asl.l #2,d4 ; Multiply plane# by four.
move.l bm_Planes(a1,d4.l),a1 ; Get address of bitplane.
moveq #0,d3
move.l wi_TextFont(a0),a2
move.w tf_YSize(a2),d3 ; Get YSize of font.
moveq #0,d1
move.l d2,d1 ; Copy bytesperrow to d1.
mulu.w d3,d1 ; YSize*BytesPerRow.
move.w d1,wi_Modulo(a0) ; Store it in WarpInfo.
moveq #0,d4
move.l d1,d4 ; Copy wi_modulo to scratch.
mulu.w wi_Top(a0),d4 ; Mul by Y offset.
add.w wi_Left(a0),d4 ; Add X offset.
move.l a1,a2 ; BPlane addr to scratch.
add.l d4,a2 ; Add offset to btpln addr.
move.l a2,wi_WindowTop(a0) ; Stick in WarpInfo.
move.l a2,wi_CurLine(a0) ; Stick in WarpInfo.
moveq #0,d2
move.w wi_Top(a0),d2 ; Copy Y top to scratch.
add.w wi_Height(a0),d2 ; Add Y height to Y top.
move.l d1,d4 ; Copy wi_modulo to scratch.
mulu.w d2,d4 ; Mul by Y offset.
add.w wi_Left(a0),d4 ; Add X offset.
move.l a1,a2 ; BPlane addr to scratch.
add.l d4,a2 ; Add offset to btpln addr.
move.l a2,wi_LastLine(a0) ; Stick in WarpInfo.
movem.l (sp)+,d0-d4/a1-a2
rts
* --------------------------------------------------------------------------
* GOTOXY NEEDS:
*
* d0 - New X position. \ All regs. but d1 preserved,
* d1 - New Y position.
*
* a0 - Pointer to initialized WarpInfo structure.
*
* NOTE: These positions are given in character locations, like everything
* else... The positions are relative to the 'window' you have
* defined using InitWarpInfo. Position 0,0 is the character in the
* top left corner of the window.
* This routine does no error checking. (You're supposed to know
* how big your window is...)
* --------------------------------------------------------------------------
GotoXY: move.w d0,wi_CurX(a0) ; Set new X position.
mulu.w wi_Modulo(a0),d1 ; Make Y an offset into window
add.l wi_WindowTop(a0),d1 ; Add this offset to the window
move.l d1,wi_CurLine(a0) ; to make it the new Y position.
rts
* --------------------------------------------------------------------------
* GETXY NEEDS:
*
* a0 - Pointer to an initialized WarpInfo structure.
*
* It returns the current X position in d0 and the current Y
* position in d1.
* --------------------------------------------------------------------------
GetXY: move.l wi_CurLine(a0),d1 ; Get current Y addr
sub.l wi_WindowTop(a0),d1 ; Sub window to get Y offset.
divu.w wi_Modulo(a0),d1 ; Should not be a remainder.
moveq #0,d0
move.w wi_CurX(a0),d0 ; Get current X position.
rts
* --------------------------------------------------------------------------
* WARPTEXT NEEDS:
*
* d0 - Number of characters to type. (count)
*
* a0 - Pointer to an initialized WarpInfo structure. (See InitWarpInfo)
* a1 - Address of string of characters to type.
*
* REGISTER USAGE FOR WARPTEXT: (All regs preserved but d0 which will be 0)
*
* d0 - Number of characters to type (count)
* d1 - Character to be emitted
* d2 - LoChar
* d3 - HiChar
* d4 - Current X position
* d5 - Scratch
* d7 - Bitplane modulo: add to get to next raster line in bitplane.
*
* a0 - Pointer to WarpInfo structure
* a1 - Address of string of characters to type
* a2 - Pointer to TextFont structure, address of tf_CharData
* a3 - Addr of Current line.
* a4 - Scratch
* a5 - Scratch
*
* STACK USAGE FOR WARPTEXT:
*
* 0(sp) - Last line
* 4(sp) - Top line
* 8(sp) - tf_YSize
* 12(sp) - tf_Modulo: add it to get to next line in font data
* 16(sp) - wi_Modulo: add it to get to next line in bitplane 'window'
* 20(sp) - Maximum (last) possible X position on a line
* --------------------------------------------------------------------------
sp_LastLine: equ 0 ; Offsets into stack to get at this data.
sp_TopLine: equ 4
sp_YSize: equ 8
sp_tf_Mod: equ 12
sp_wi_Mod: equ 16
sp_LastX: equ 20
NoChar: equ 256 ; This is where the empty-box char is. ???
WarpText: movem.l d1-d5/d7/a2-a5,-(sp)
moveq #0,d4
move.w wi_CurX(a0),d4 ; Get current X position.
moveq #0,d5
move.w wi_LastX(a0),d5 ; Get maximum X position.
move.l d5,-(sp) ; Stick it on stack. (1st item)
move.w wi_Modulo(a0),d5 ; Get wi_Modulo.
move.l d5,-(sp) ; Stick it on stack. (2nd item)
move.l wi_TextFont(a0),a2 ; Use TextFont to get some stuff:
moveq #0,d2
move.b tf_LoChar(a2),d2 ; Get tf_LoChar.
moveq #0,d3
move.b tf_HiChar(a2),d3 ; Get tf_HiChar.
move.w tf_Modulo(a2),d5 ; Get tf_Modulo.
move.l d5,-(sp) ; Stick it on stack. (3rd item)
move.w tf_YSize(a2),d5 ; Get tf_YSize
move.l d5,-(sp) ; Stick it on stack. (4th item)
move.l tf_CharData(a2),a2 ; Replace textfont w/ tf_Chardata.
move.l wi_WindowTop(a0),a4 ; Get addr of wi_WindowTop.
move.l a4,-(sp) ; Stick it on stack. (5th item)
move.l wi_LastLine(a0),a4 ; Get addr of wi_LastLine.
move.l a4,-(sp) ; Stick it on stack. (6th item)
move.l wi_CurLine(a0),a3 ; Get addr of wi_CurLine.
moveq #0,d7
move.w wi_BPMod(a0),d7 ; Get wi_BPMod.
subq #1,d0 ; Take one from count.
moveq #0,d1 ; Clear d1 because using .b size.
subq #1,d4 ; Take one from Current X.
DoNextChar: addq #1,d4 ; Add 1 to Current X.
DoNextSinAdd: move.b (a1)+,d1 ; Move char to emit to d1.
cmpi.b #32,d1 ; Is it a space?
beq Blank
cmp.b d2,d1 ; Compare with LoChar.
blt BoffoChar ; May be a LF, FF, CR, etc.
cmp.b d3,d1 ; Compare with HiChar.
blt DoNoChar
move.l a2,a4 ; Copy tf_CharData to scratch.
sub.l d2,d1 ; Sub LoChar from char.
adda.l d1,a4 ; Add char to tf_CharData.
DoChar: move.l a3,a5 ; Copy current line to scratch.
adda.l d4,a5 ; Add XPos to current line.
move.l sp_YSize(sp),d5 ; YSize is loop count.
subq.l #1,d5
MoveChar: move.b (a4),(a5) ; Move line of char to bitplane.
adda.l sp_tf_Mod(sp),a4 ; Add tf_Modulo to tf_Chardata.
adda.l d7,a5 ; Add wi_BPMod to bitplane.
dbra d5,MoveChar
Blank: cmp.l sp_LastX(sp),d4 ; Compare max X and Current X...
ble GotoDoNext ; Do next if current <= max.
DoLF: moveq #0,d4 ; Xpos is zero now.
DoCR: cmpa.l (sp),a3 ; CMP sp_LastLine with current.
beq GotoNSA ; Wrap on line if equ.
adda.l sp_wi_Mod(sp),a3 ; Point at next line.
bra GotoNSA ; Do another character.
DoNoChar: move.l a2,a4 ; Copy tf_Chardata to scratch.
add.l #NoChar,a4 ; Point at empty-box char.
bra DoChar ; Do the empty-box char.
BoffoChar: cmpi.l #10,d1 ; Is is a linefeed?
beq DoLF
cmpi.l #12,d1 ; Is it a formfeed?
beq DoFF
cmpi.l #13,d1 ; Is it a CR?
beq DoCR
bra DoNoChar ; Fine. Put up the box.
DoFF: moveq #0,d4 ; Make X pos zero. | It doesn't
move.l sp_TopLine(sp),a3 ; Point at top | CLS yet.
bra GotoNSA
GotoDoNext: dbra d0,DoNextChar ; Keep looping?
bra WindUp ; Loop is done. Clean up & bail.
GotoNSA: dbra d0,DoNextSinAdd ; Do NextChar without adding.
WindUp: addq.l #8,sp ; Get rid of stuff kept on stack.
addq.l #8,sp
addq.l #8,sp
move.w d4,wi_CurX(a0) ; Store current X for next time.
move.l a3,wi_CurLine(a0) ; Store current Y for next time.
movem.l (sp)+,d1-d5/d7/a2-a5
rts
END